package met.cs664.ai.cox.soc.strategies.placement;

import soc.game.SOCBoard;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Scores placements on synergy between resources. Different resources work better together, such as brick and wood.
 * Both brick and wood are required to build roads and our initial settlements. Other great combos are wheat and ore,
 * which are both used to build cities.
 *
 * @author mcox
 */
public class ResourceSynergy extends AbstractEvaluator implements PlacementEvaluator {

    public static final int CLAY = 1 << 0;
    public static final int ORE = 1 << 1;
    public static final int SHEEP = 1 << 2;
    public static final int WHEAT = 1 << 3;
    public static final int WOOD = 1 << 4;

    // Beneficial early game combinations
    public static final int CLAY_WOOD = CLAY | WOOD;
    public static final int CLAY_WOOD_ORE = CLAY | WOOD | ORE;
    public static final int CLAY_WOOD_SHEEP = CLAY | WOOD | SHEEP;
    public static final int CLAY_WOOD_WHEAT = CLAY | WOOD | WHEAT;
    public static final int ORE_WHEAT = ORE | WHEAT;
    public static final int ORE_WHEAT_CLAY = ORE | WHEAT | CLAY;
    public static final int ORE_WHEAT_SHEEP = ORE | WHEAT | SHEEP;
    public static final int ORE_WHEAT_WOOD = ORE | WHEAT | WOOD;

    // Harmful early game combination
    public static final int CLAY_ORE = CLAY | ORE;
    public static final int CLAY_SHEEP = CLAY | SHEEP;
    public static final int CLAY_WHEAT = CLAY | WHEAT;
    public static final int WOOD_ORE = WOOD | ORE;
    public static final int WOOD_SHEEP = WOOD | SHEEP;
    public static final int WOOD_WHEAT = WOOD | WHEAT;
    public static final int ORE_SHEEP = ORE | SHEEP;
    public static final int ORE_SHEEP_WOOD = ORE | SHEEP | WOOD;
    public static final int CLAY_ORE_SHEEP = CLAY | ORE | SHEEP;

    private final Map<Integer, Integer> COMBO_TO_SCORE;

    /**
     * Builds an array that maps SOCBoard resource types to our bit position
     *
     * resource to index
     * DESERT_HEX = 0;
     * CLAY_HEX = 1;
     * ORE_HEX = 2;
     * SHEEP_HEX = 3;
     * WHEAT_HEX = 4;
     * WOOD_HEX = 5;
     */
    public static final int [] RESOURCE_BIT = new int [] { 0, CLAY, ORE, SHEEP, WHEAT, WOOD };

    public ResourceSynergy(float weight) {
        super(weight);
        COMBO_TO_SCORE = new HashMap<Integer, Integer>();
        COMBO_TO_SCORE.put(CLAY_WOOD, 2);
        COMBO_TO_SCORE.put(CLAY_WOOD_ORE, 2);
        COMBO_TO_SCORE.put(CLAY_WOOD_SHEEP, 2);
        COMBO_TO_SCORE.put(CLAY_WOOD_WHEAT, 2);
        COMBO_TO_SCORE.put(ORE_WHEAT, 1);
        COMBO_TO_SCORE.put(ORE_WHEAT_CLAY, 1);
        COMBO_TO_SCORE.put(ORE_WHEAT_SHEEP, 1);
        COMBO_TO_SCORE.put(ORE_WHEAT_WOOD, 1);
        COMBO_TO_SCORE.put(CLAY_ORE, -1);
        COMBO_TO_SCORE.put(CLAY_SHEEP, -1);
        COMBO_TO_SCORE.put(CLAY_WHEAT, -1);
        COMBO_TO_SCORE.put(WOOD_ORE, -1);
        COMBO_TO_SCORE.put(WOOD_SHEEP, -1);
        COMBO_TO_SCORE.put(WOOD_WHEAT, -1);
        COMBO_TO_SCORE.put(ORE_SHEEP, -2);
        COMBO_TO_SCORE.put(ORE_SHEEP_WOOD, -2);
        COMBO_TO_SCORE.put(CLAY_ORE_SHEEP, -1);
    }

    public String toString() {
        return "ResourceSynergy";
    }

    @Override
    public void evaluateCandidates(SOCBoard board, List<PlacementCandidate> candidates) {
        for (PlacementCandidate candidate : candidates) {
            int hexTypes = 0;
            for (int hexCoord : getAdjacentHexesToNode(candidate.getCoord())) {
                int hexType = board.getHexTypeFromCoord(hexCoord);
                if (hexType >= 0 && hexType < RESOURCE_BIT.length) {
                    hexTypes |= RESOURCE_BIT[hexType];
                }
            }

            for (Map.Entry<Integer, Integer> entries : COMBO_TO_SCORE.entrySet()) {
                if (entries.getKey() == hexTypes) {
                    candidate.updateWeight(getWeight() * entries.getValue());
                }
            }
        }
    }
}
